/*
 * @Author: zhangxf
 * @Date: 2023-08-29 16:23:58
 * @Last Modified by: zhangxf
 * @Last Modified time: 2023-09-18 14:05:43
 */
import qs from "qs";
import xss from "xss";
import store from "@/template/store";
import wx from "weixin-js-sdk";
const $store = store();
export const computed = {
  /**
   * @description 获取浏览器版本信息
   * @author zhangxf
   * @date 29/08/2023 04:08:09
   * @return {*}
   */
  $browser() {
    var u = navigator.userAgent;
    //		,app = navigator.appVersion;
    return {
      //移动终端浏览器版本信息
      wx: u.indexOf("MicroMessenger") > -1, //微信
      qq: u.indexOf(" qq") > -1, //qq
      trident: u.indexOf("Trident") > -1, //IE内核
      presto: u.indexOf("Presto") > -1, //opera内核
      webKit: u.indexOf("AppleWebKit") > -1, //苹果、谷歌内核
      gecko: u.indexOf("Gecko") > -1 && u.indexOf("KHTML") == -1, //火狐内核
      mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
      iframe: window.parent != window, //是否为iframe
      ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
      android: u.indexOf("Android") > -1 || u.indexOf("Linux") > -1, //android终端或uc浏览器
      iPhone: u.indexOf("iPhone") > -1, //是否为iPhone或者QQHD浏览器
      iPad: u.indexOf("iPad") > -1, //是否iPad
      webApp: u.indexOf("Safari") == -1, //是否web应该程序，没有头部与底部
    };
  },
};
export const methods = {
  /**
   * @description 生成36位uuid
   * @author zhangxf
   * @date 29/08/2023 04:08:45
   * @return {string}
   */
  $uuid() {
    function S4() {
      return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    function guid() {
      return (
        S4() +
        S4() +
        "-" +
        S4() +
        "-" +
        S4() +
        "-" +
        S4() +
        "-" +
        S4() +
        S4() +
        S4()
      );
    }
    return guid();
  },
  /**
   * @description 将a_b转换为小驼峰
   * @author zhangxf
   * @date 29/08/2023 04:08:57
   * @param {string} str 源字符串
   * @return {string}
   */
  $toHump(str) {
    return str.replace(/(_.)/g, function (l) {
      return l.substr(1).toLocaleUpperCase();
    });
  },
  /**
   * @description 插入从index开始的string任意部分
   * @author zhangxf
   * @date 29/08/2023 04:08:37
   * @param {string} str 源字符串
   * @param {number} index 插入位置index
   * @param {string} changeStr 要插入的字符串
   * @return {string}
   */
  $changeStr(str, index, changeStr) {
    return (
      str.substr(0, index) + changeStr + str.substr(index + changeStr.length)
    );
  },
  /**
   * @description 将小驼峰转为a_b
   * @author zhangxf
   * @date 29/08/2023 04:08:10
   * @param {string} str 源字符串
   * @return {string}
   */
  $fromHump(str) {
    if (str[0].match(/^[A-Z]$/)) {
      str = this.$changeStr(str, 0, str[0].toLocaleLowerCase());
    }
    return str.replace(/([A-Z])/g, function (l) {
      return `_${l}`.toLocaleLowerCase();
    });
    // str.replace(/([A-Z].)/g, function (l) {
    //   return `_${l[0].toLocaleLowerCase()}${l[1]}`
    // })
  },
  /**
   * @description 扩展引用类型识别的typeof函数
   * @author zhangxf
   * @date 29/08/2023 04:08:19
   * @param {string} arg 要识别类型的参数
   */
  $typeof: (arg) =>
    Object.prototype.toString
      .call(arg)
      .split("[object ")[1]
      .split("]")[0]
      .toLocaleLowerCase(),
  /**
   * @description 递归克隆对象
   * @author zhangxf
   * @date 29/08/2023 04:08:35
   * @param {object} data 源对象
   * @return {object}  新对象
   */
  $deepClone(data) {
    var t = this.$typeof(data),
      o,
      i,
      ni;

    if (t === "array") {
      o = [];
    } else if (t === "object") {
      o = {};
    } else {
      return data;
    }

    if (t === "array") {
      for (i = 0, ni = data.length; i < ni; i++) {
        o.push(this.$deepClone(data[i]));
      }
      return o;
    } else if (t === "object") {
      for (i in data) {
        o[i] = this.$deepClone(data[i]);
      }
      return o;
    }
  },
  /**
   * @description 获取urlQuery参数
   * @author zhangxf
   * @date 29/08/2023 04:08:03
   * @param {string} name 要获取的参数名
   * @param {string} url 如果不是获取当前地址栏url参数，则需要传入指定url地址
   * @return {string}
   */
  $getQuery(name, url) {
    var search = window.location.search;
    if (url) {
      var a = document.createElement("a");
      a.href = url;
      search = a.search;
    }
    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
    var r = search.substr(1).match(reg);
    if (r != null) return r[2];
    return null;
  },
  /**
   * @description 获取URL的所有查询参数
   * @author zhangxf
   * @date 29/08/2023 04:08:04
   * @param {string} url 如果不是获取当前地址栏url参数，则需要传入指定url地址
   * @return {object}
   */
  $getUrlQueryParams(url) {
    let href = document.location.href.replace(/#/g, "");
    if (url) href = url.replace(/#/g, "");
    let a = document.createElement("a");
    a.href = href;
    return qs.parse(a.search.replace(/\?/, ""));
  },
  /**
   * @description 给任意url增加baseUrl后返回拼接好的地址
   * @author zhangxf
   * @date 29/08/2023 04:08:30
   * @param {string} url 源地址，url中可使用模板{key}进行后续的值替换
   * @param {object} maps 源地址用于url参数替换的maps对象
   * @return {string} 拼接后的址
   */
  $getCtx(url, maps) {
    let baseUrl = this.$baseConfigs.baseUrl;
    baseUrl =
      baseUrl[baseUrl.length - 1] === "/"
        ? baseUrl.substring(0, baseUrl.length - 1)
        : baseUrl;
    url = url[0] === "/" ? url.substr(1) : url;
    if (maps && typeof maps == "object") {
      url = url.replace(/\{(\w+)\}/gi, (val) => {
        let key = val.substring(1, val.length - 1);
        return maps[key];
      });
    }
    return `${baseUrl}/${url}`;
  },
  /**
   * @description 计时器函数
   * @author zhangxf
   * @date 29/08/2023 04:08:46
   * @param {number} times 要倒计时的毫秒数
   * @param {function} [ca=() => {}] 计时完成的回调函数
   */
  $countDown(times, ca = () => { }) {
    var timer = null;
    timer = setInterval(function () {
      var day = 0,
        hour = 0,
        minute = 0,
        second = 0; //时间默认值
      if (times > 0) {
        day = Math.floor(times / (60 * 60 * 24));
        hour = Math.floor(times / (60 * 60)) - day * 24;
        minute = Math.floor(times / 60) - day * 24 * 60 - hour * 60;
        second =
          Math.floor(times) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
      }
      if (day <= 9) day = "0" + day;
      if (hour <= 9) hour = "0" + hour;
      if (minute <= 9) minute = "0" + minute;
      if (second <= 9) second = "0" + second;
      ca({ day, hour, minute, second, timer, times });
      times--;
    }, 1000);
    if (times <= 0) {
      clearInterval(timer);
    }
  },
  /**
   * @description 卡号脱敏函数
   * @author zhangxf
   * @date 29/08/2023 04:08:50
   * @param {string} account 16-18 原卡号
   * @return {siring} 脱敏后的卡号
   */
  $dealAccountNo(account) {
    if (!account || !(account && account.startsWith)) return "";
    if (account.startsWith("1")) {
      if (account.length >= 17) {
        account =
          account.substring(0, 4) +
          " **** **** " +
          account.substring(account.length - 4);
      }
    }
    if (account.startsWith("6")) {
      if (account.length >= 16) {
        account =
          account.substring(0, 4) +
          " **** **** " +
          account.substring(account.length - 4);
      }
    }
    return account;
  },
  /**
   * @description 压缩图片
   * @param {file} file 压缩文件
   * @param {number} compressThreshold 开启压缩的阈值，默认 5M
   * @param {boolean} openCompress 是否开启压缩，默认 true
   * @param {number} pictureQuality 压缩比，默认 0.92
   * @return {file} 压缩后的文件
   */
  $compressFile(
    file,
    compressThreshold = 5,
    openCompress = true,
    pictureQuality = 0.92
  ) {
    console.log("========== Entry Compress File Function ==========");
    console.log("before compress file: ", file);
    //判断是否是图片类型
    const isAccept = [
      "image/png",
      "image/jpeg",
      "image/jpg",
      "image/gif",
    ].includes(file.type);
    if (isAccept) {
      const fileSize = file.size / 1024 / 1024;
      console.log(
        "before compress, the file size is : ",
        fileSize.toFixed(2) + " M"
      );
      //当开启图片压缩且图片大小大于等于压缩阈值,进行压缩
      if (fileSize >= compressThreshold && openCompress) {
        //判断浏览器内核是否支持base64图片压缩
        if (typeof FileReader === "undefined") {
          return file;
        } else {
          try {
            return new Promise((resolve) => {
              //声明FileReader文件读取对象
              const reader = new FileReader();
              reader.readAsDataURL(file);
              reader.onload = () => {
                // 生成canvas画布
                const canvas = document.createElement("canvas");
                // 生成img
                // const img = document.createElement('img');
                const img = new Image();
                img.src = reader.result;
                img.onload = () => {
                  const ctx = canvas.getContext("2d");
                  //原始图片宽度、高度
                  const originImageWidth = img.width,
                    originImageHeight = img.height;
                  //默认最大尺度的尺寸限制在（1920 * 1080）
                  const maxWidth = 1920,
                    maxHeight = 1080,
                    ratio = maxWidth / maxHeight;
                  //目标尺寸
                  let targetWidth = originImageWidth,
                    targetHeight = originImageHeight;
                  //当图片的宽度或者高度大于指定的最大宽度或者最大高度时,进行缩放图片
                  if (
                    originImageWidth > maxWidth ||
                    originImageHeight > maxHeight
                  ) {
                    //超过最大宽高比例
                    if (originImageWidth / originImageHeight > ratio) {
                      //宽度取最大宽度值maxWidth,缩放高度
                      targetWidth = maxWidth;
                      targetHeight = Math.round(
                        maxWidth * (originImageHeight / originImageWidth)
                      );
                    } else {
                      //高度取最大高度值maxHeight,缩放宽度
                      targetHeight = maxHeight;
                      targetWidth = Math.round(
                        maxHeight * (originImageWidth / originImageHeight)
                      );
                    }
                  }
                  // canvas对图片进行缩放
                  canvas.width = targetWidth;
                  canvas.height = targetHeight;
                  // 清除画布
                  ctx?.clearRect(0, 0, targetWidth, targetHeight);
                  // 绘制图片
                  ctx?.drawImage(img, 0, 0, targetWidth, targetHeight);
                  // quality值越小,图像越模糊,默认图片质量为0.92
                  const imageDataURL = canvas.toDataURL(
                    file.type || "image/jpeg",
                    pictureQuality
                  );
                  // 去掉URL的头,并转换为byte
                  const imageBytes = window.atob(imageDataURL.split(",")[1]);
                  // 处理异常,将ascii码小于0的转换为大于0
                  const arrayBuffer = new ArrayBuffer(imageBytes.length);
                  const uint8Array = new Uint8Array(arrayBuffer);
                  for (let i = 0; i < imageBytes.length; i++) {
                    uint8Array[i] = imageBytes.charCodeAt(i);
                  }
                  const mimeType = imageDataURL
                    ?.split(",")?.[0]
                    ?.match(/:(.*?);/)?.[1];
                  const newFile = new File([uint8Array], file.name, {
                    type: mimeType || "image/jpeg",
                  });
                  console.log(
                    "after compress, the file size is : ",
                    (newFile.size / 1024 / 1024).toFixed(2) + "M"
                  );
                  console.log("after compress file: ", newFile);
                  resolve(newFile);
                };
              };
              reader.onerror = () => {
                return file;
              };
            })
              .then((res) => {
                return res;
              })
              .catch(() => {
                return file;
              });
          } catch (e) {
            //压缩出错,直接返回原file对象
            return file;
          }
        }
      } else {
        //不需要压缩，直接返回原file对象
        return file;
      }
    } else {
      //非图片文件,不进行压缩,直接返回原file对象
      return file;
    }
  },
  /**
   * @description blob转base64
   * @author zhangxf
   * @date 29/08/2023 04:08:06
   * @param {blob} blob 二进制源
   * @return {string} 输出的base64
   */
  $getImageBase64(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();
      reader.readAsDataURL(blob);
      reader.onload = () => {
        const base64 = reader.result;
        resolve(base64);
      };
      reader.onerror = (error) => reject(error);
    });
  },
  /**
   * @description 将图片对象加载到canvas
   * @author zhangxf
   * @date 29/08/2023 04:08:55
   * @param {image} image 源image对象
   * @param {string} maxWidth 图片宽/高，不设置则为图片本身宽高
   * @return {canvas} 输出canvas对象
   */
  $imgToCanvas(image, maxWidth) {
    var canvas = document.createElement("canvas");
    var rage = image.width / image.height;
    if (maxWidth) {
      if (image.height > image.width) {
        canvas.height = maxWidth;
        canvas.width = maxWidth * rage;
      } else {
        canvas.width = maxWidth;
        canvas.height = maxWidth / rage;
      }
    } else {
      canvas.width = image.width;
      canvas.height = image.height;
    }
    canvas
      .getContext("2d")
      .drawImage(
        image,
        0,
        0,
        image.width,
        image.height,
        0,
        0,
        canvas.width,
        canvas.height
      );
    return canvas;
  },
  /**
   * @description 将base64图片压缩到指定大小以下
   * @author zhangxf
   * @date 29/08/2023 04:08:39
   * @param {string} baseImg 原始base64格式的图片
   * @param {number} [maxSize=200] 设置阈值 kb
   * @return {string} 压缩后的图片base64
   */
  $compressImgBySize(baseImg, maxSize = 200, maxWidth = 1024) {
    return new Promise((resolve) => {
      // 计算图片大小
      const strLength = baseImg.length;
      const fileLength = parseInt(strLength - (strLength / 8) * 2);
      let size = parseInt((fileLength / 1024).toFixed(2));

      // 判断图片是否符合指定大小要求
      if (size <= maxSize) {
        resolve(baseImg);
        return;
      }

      // 创建image对象
      const img = new Image();
      if (baseImg.indexOf("data:image/") !== -1) {
        img.src = baseImg;
      } else {
        img.src = "data:image/jpeg;base64," + baseImg;
      }

      img.onload = () => {
        // 把image对象 转换为 canvas对象
        const canvas = this.$imgToCanvas(img, maxWidth);
        let resUrl = "";
        // 图片质量，范围：0 ~ 1
        let quality = 0.9;

        // 当图片大小大于指定maxSize，图片质量大于0时继续通过降低图片资料来压缩
        while (size > maxSize && quality > 0) {
          // 在canvas上绘制该HTMLImageElement，得到图片base64
          resUrl = canvas
            .toDataURL("image/jpeg", quality)
            .replace(/^data:image\/\w+;base64,/, "");
          const resLength = resUrl.length;
          // 计算绘制出的base64图片大小
          const resFileLength = parseInt(resLength - (resLength / 8) * 2);
          size = parseInt((resFileLength / 1024).toFixed(2));
          // 降低图片质量
          quality = (quality - 0.1).toFixed(1) - 0;
        }
        resolve(resUrl);
      };
      img.onerror = () => {
        resolve(baseImg);
      };
    });
  },
  /**
   * @description baser64转换为原始字符串
   * @author zhangxf
   * @date 29/08/2023 04:08:27
   * @param {siring} base64String 被转换后的base64字符串
   * @return {siring} 原始字符串
   */
  $base64ToArrayBufferToString(base64String) {
    // 解码 base64 字符串为原始字符串
    const decodedString = new TextDecoder().decode(
      new Int8Array(
        atob(base64String)
          .split("")
          .map((char) => char.charCodeAt(0))
      )
    );
    return decodedString;
  },
  /**
   * 将以base64的图片url数据转换为Blob
   * @param urlData 用url方式表示的base64图片数据
   */
  $convertBase64UrlToBlob(urlData) {
    // var arr = urlData.split(","),
    // mime = arr[0].match(/:(.*?);/)[1],
    var bstr = atob(urlData),
      n = bstr.length,
      u8arr = new Int8Array(n);
    while (n--) {
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new Blob([u8arr], { type: "image/jpeg" });
  },
  /**
   * @description 将base64转换为urlbase64
   * @author zhangxf
   * @date 29/08/2023 04:08:40
   * @param {siring} str 原始base64
   * @return {string} urlbase64
   */
  $base64Urldecode(str) {
    str = (str + "").toString();
    if (str % 4 !== 0) {
      for (var i = 0; i <= str % 4; i++) {
        str += "=";
      }
    }
    return str.replace(/_/g, "/").replace(/-/g, "+");
  },
  /**
   * @description 获取项目token，获取顺序为query>hash>sessionStorage
   * @author zhangxf
   * @date 29/08/2023 05:08:07
   * @return {string} token
   */
  $getToken() {
    let hash = window.location.hash;
    let tokenId = this.$getQuery("token");
    if (hash.indexOf("token=") != -1) {
      tokenId = this.$getQuery("token", hash ? hash.substr(1) : "");
    }
    if (tokenId && tokenId[tokenId.length - 1] === "/") {
      tokenId = tokenId.substring(0, tokenId.length - 1);
    }
    if (tokenId) window.sessionStorage.setItem("token", tokenId);
    // else if (store().getters.token)
    //   window.sessionStorage.setItem("token", store().getters.token);
    return window.sessionStorage.getItem("token");
  },
  /**
   * @description 清除token
   * @author zhangxf
   * @date 29/08/2023 05:08:48
   */
  $clearToken() {
    window.sessionStorage.removeItem("token");
  },
  /**
   * @description 拦截error对象过滤http请求异常的常用错误
   * @author zhangxf
   * @date 29/08/2023 05:08:57
   * @param {Error} error 拦截器返回的error对象
   * @return {string} 过滤后的错误信息字符串
   */
  $getErrorMessage(error) {
    let desc = error?.data?.msg || error.message;
    if (error.message && error.message.includes("timeout")) {
      desc = "通讯请求超时，请稍后再试！";
    } else if (error.message && error.message.includes("Network")) {
      desc = "网络未连接，请检查网络后再试！";
    }
    return desc || "系统异常，请稍后再试！";
  },
  /**
   * @description 获取字符串Unicode长度 汉字以三字节计算
   * @author fengwc
   * @date 29/08/2023 05:08:55
   * @param {string} str 源字符串
   * @return {number}  字符串Unicode长度
   */
  $validStrLength(str) {
    let len = 0;
    for (let i = 0; i < str.length; i++) {
      let a = str.charAt(i);
      const reg = /^[\u4e00-\u9fa5]/gi;
      if (reg.test(a)) {
        len += 3;
      } else {
        len += 1;
      }
    }
    return len;
  },
  /**
   * @description 根据json字符串获取json属性
   * @author zhangxf
   * @date 29/08/2023 05:08:00
   * @param {string} str 源json表达式字符串 如“a.b.c”
   * @param {string} [symbol="."]  切分json表达式字符串的分隔符，默认为“.”
   * @param {object} this 通过改变this指向传入json对象本身 $tryJson.bind(jsonObj)(str)
   * @return {*} json表达式指向的json对象本身的属性值
   */
  $tryJson(str, symbol = ".") {
    let aw = str.split(symbol);
    return aw.reduce((prev, cur) => {
      return prev[cur] ? prev[cur] : undefined;
    }, this);
  },
  /**
   * @description xss过滤
   * @author zhangxf
   * @date 30/08/2023 06:08:00
   * @param {string} str 过滤前
   * @return {string} 过滤后
   */
  $xss(str) {
    return xss(str);
  },
  /**
   * @description
   * @author zhangxf
   * @date 30/08/2023 07:08:12
   * @param {object} opt //详细查看 store dialog
   * @return {promise}
   */
  $alert(opt) {
    let desc = "";
    if (typeof opt === "string") desc = opt;
    return $store.dispatch("dialog/show", {
      desc,
      ...opt,
      type: 0,
    });
  },
  /**
   * @description
   * @author zhangxf
   * @date 30/08/2023 07:08:12
   * @param {object} opt //详细查看 store dialog
   * @return {promise}
   */
  $confirm(opt) {
    let desc = "";
    if (typeof opt === "string") desc = opt;
    return $store.dispatch("dialog/show", {
      desc,
      ...opt,
      type: 1,
    });
  },
  /**
   * @description 递归查找对象指定属性所在的对象
   * @author zhangxf
   * @date 01/09/2023 03:09:46
   * @param {*} obj
   * @param {*} property
   * @param {*} value
   * @return {*}
   */
  $searchPropertyValue(obj, property, value) {
    // 检查当前对象是否包含要查找的属性
    if (obj[property] === value) {
      return obj;
    }

    // 检查当前对象是否为数组
    if (Array.isArray(obj)) {
      // 迭代数组中的每个元素
      for (let i = 0; i < obj.length; i++) {
        const result = this.$searchPropertyValue(obj[i], property, value);
        if (result) {
          return result;
        }
      }
    } else {
      // 迭代对象的所有属性
      for (let key in obj) {
        // 检查属性值是否为对象，如果是则进行递归调用
        if (typeof obj[key] === "object" && obj[key] !== null) {
          const result = this.$searchPropertyValue(obj[key], property, value);
          if (result) {
            return result;
          }
        }
      }
    }

    // 如果未找到匹配的属性值，则返回null
    return null;
  },
  /**
   * @description 回到小程序指定页面
   * @author zhangxf
   * @date 11/09/2023 06:09:30
   */
  $toWxAppPage(url) {
    wx.miniProgram.redirectTo({
      url,
    });
  },
  /**
   * @description 
   * @author zhangxf
   * @date 11/09/2023 06:09:19
   */
  $toWxBackHome() {
    this.$toWxAppPage(
      `/`
    );
  },
  /**
   * @date 2023/9/18 14:03:59
   * @description 全局rage格式化
   * @author zhangxf
   * @param {number} rage
   * @return {string} 拼接好的rage
   */
  $getRage(rage) {
    return rage + "%";
  },
  /**
   * @description 根据参数拼接成path
   * @author zhangxf
   * @date 18/09/2023 02:09:24
   * @param {string} 若干个path的string
   * @return {string} 拼接好的path
   */
  $pathsJoin() {
    let arr = Array.from(arguments);
    let host = "";
    let paths = [];
    arr.forEach((path) => {
      // if (path.substr(-1) === "/") {
      if (path.endsWith("/")) {
        path = path.substring(0, path.length - 1);
      }
      if (path.match(/:\/\/|^\/\//)) {
        if (!host) {
          host = path;
          paths.unshift(path);
        } else {
          path = path.replace(/(.+:\/\/)|(^\/\/)/, "");
          paths.push(path);
        }
      } else {
        // if (path.charAt(0) === "/") {
        if (path.startsWith("/")) {
          path = path.substr(1);
        }
        if (path) paths.push(path);
      }
    });
    if (
      paths[0] &&
      paths[0].charAt(0) !== "/" &&
      !paths[0].match(/:\/\/|^\/\//)
    )
      paths[0] = `/${paths[0]}`;
    return paths.join("/");
  },
};
export default { methods, computed };

/**
 * @date 2023/8/29 17:20:09
 * @description Date全局的format方法
 * @author zhangxf
 * @param {string} fmt 时间字符串的表达式 年:y|月:M|日:d|时:h|分:m|秒:s|毫秒:S|季度:q ,如：yyyy-MM-dd hh:mm:ss
 * @return {string} 格式化后的时间字符串
 */
Date.prototype.Format = function (fmt) {
  // author: meizz
  var o = {
    "M+": this.getMonth() + 1, // 月份
    "d+": this.getDate(), // 日
    "h+": this.getHours(), // 小时
    "m+": this.getMinutes(), // 分
    "s+": this.getSeconds(), // 秒
    "q+": Math.floor((this.getMonth() + 3) / 3), // 季度
    S: this.getMilliseconds(), // 毫秒
  };
  if (/(y+)/.test(fmt)) {
    fmt = fmt.replace(
      RegExp.$1,
      (this.getFullYear() + "").substr(4 - RegExp.$1.length)
    );
  }
  for (var k in o) {
    if (new RegExp("(" + k + ")").test(fmt)) {
      fmt = fmt.replace(
        RegExp.$1,
        RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)
      );
    }
  }
  return fmt;
};
